table of contents
CAPGET(2) | Руководство программиста Linux | CAPGET(2) |
ИМЯ¶
capget, capset - установка/получение мандатов нити(ей)
ОБЗОР¶
#include <sys/capability.h>
int capget(cap_user_header_t hdrp, cap_user_data_t datap);
int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
ОПИСАНИЕ¶
Начиная с Linux 2.2, полномочия суперпользователя (root) были разделены на несколько отдельных мандатов. У каждой нити есть набор действующих мандатов, определяющих какие возможности (если есть) она может в данный момент использовать. Каждая нить также имеет набор унаследованных мандатов, который мог быть передан через вызов execve(2), и набор разрешённых мандатов, которые она может сделать эффективными или передать потомкам.
Данные функции представляют собой низкоуровневый интерфейс ядра для получения и установки мандатов нити. Кроме того, что эти системные вызовы есть только в Linux, из-за них, вероятно, изменится программный интерфейс ядра; с каждой новой версией ядра эти функции используются всё чаще (в частности, типы cap_user_*_t), но старые программы работают как и прежде.
Переносимыми интерфейсами являются cap_set_proc(3) и cap_get_proc(3); если возможно, в приложениях используйте именно их. Если требуется использовать расширения Linux, используйте простые в использовании capsetp(3) и capgetp(3).
Подробная информация¶
На данный момент в ядре определены следующие структуры:
#define _LINUX_CAPABILITY_VERSION_1 0x19980330 #define _LINUX_CAPABILITY_U32S_1 1 #define _LINUX_CAPABILITY_VERSION_2 0x20071026 #define _LINUX_CAPABILITY_U32S_2 2 typedef struct __user_cap_header_struct {
__u32 version;
int pid; } *cap_user_header_t; typedef struct __user_cap_data_struct {
__u32 effective;
__u32 permitted;
__u32 inheritable; } *cap_user_data_t;
effective, permitted, inheritable — это битовые маски мандатов, определённых в capability(7). Заметим, что значения CAP_* являются индексами битов и требуется сдвиг битов перед выполнением операции ИЛИ над битовыми полями. Чтобы определить структуры для передачи в системный вызов, используйте имена struct __user_cap_header_struct и struct __user_cap_data_struct, так как typedef описаны только указатели.
Ядра до версии 2.6.25 предъявляют 32-битные мандаты с версией _LINUX_CAPABILITY_VERSION_1, а ядра 2.6.25+ предъявляют 64-битные мандаты с версией _LINUX_CAPABILITY_VERSION_2. Заметим, что в 64-битных мандатах используются datap[0] и datap[1], в то время как в 32-битных только datap[0].
Другое изменение, влияющее на поведение этих системных вызовов, поддержка ядром файловых мандатов (поддержка мандата VFS). Данная поддержка включается параметром компиляции (добавлен в ядро версии 2.6.24).
С помощью вызова capget() можно выполнить проверку мандатов любого процесса, указав его ID в поле hdrp->pid.
Ядро с поддержкой мандатов VFS¶
При поддержке мандатов VFS существует файл-атрибутный метод для добавления мандатов привилегированных исполняемым файлам. Данная модель привилегий делает устаревшей ядерную поддержку асинхронного назначения мандатов процессов. То есть с поддержкой VFS в вызове capset() разрешено только значение hdrp->pid равное 0 или getpid(2), что приводит к одному результату.
Ядро без поддержки мандатов VFS¶
Когда ядро не поддерживает мандаты VFS, вызовом capset() можно управлять мандатами нити, указав значение не равное нулю в поле pid из hdrp, или мандатами вызывающей нити, указав в pid значение 0. Если pid указывает на процесс с одной нитью, то значением pid может быть ID обычного процесса; управление нитью в многонитиевом процессе требует ID нити такого же типа, что и возвращается gettid(2). У capset() pid также может быть: -1 — выполнить изменение у всех нитей, за исключением вызывающей и init(8); меньше -1 — выполнить изменение всех членов группы процесса, чей ID равен -pid.
Подробную информацию о данных смотрите в capabilities(7).
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
Вызовы будут завершаться с ошибкой EINVAL и устанавливать поле version в hdrp в предпочитаемое ядром значение _LINUX_CAPABILITY_VERSION_?, если указано неподдерживаемое значение version. Таким способом можно проверить какая версия мандатов является предпочтительной.
ОШИБКИ¶
- EFAULT
- Неправильный адрес памяти. Значение hdrp не должно быть равно NULL. Значение datap может быть NULL только, когда пользователь пытается определить предпочтительную версию формата мандатов, поддерживаемую ядром.
- EINVAL
- Один из аргументов неправилен.
- EPERM
- Была сделана попытка добавить мандат к списку разрешённых, эффективных или унаследованных мандатов, но это не разрешено согласно списку разрешённых.
- EPERM
- Вызывающий процесс пытается использовать capset() для изменения мандатов не своей нити, но ему не хватает на это прав. Для ядер, поддерживающих мандаты VFS, это всегда запрещено. Для ядер без поддержки VFS требуется мандат CAP_SETPCAP. (Неправильная работа ядер до версии 2.6.11 приводила к тому, что эта ошибка также возникала, если нить без данного мандата пыталась изменить свои собственные мандаты, указывая в поле pid ненулевое значение (т.е. значение, возвращаемое getpid(2)), а не 0).
- ESRCH
- Такой нити нет.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
Данные системные вызовы есть только в Linux.
ЗАМЕЧАНИЯ¶
Переносимый
интерфейс
для
запроса и
установки
мандатов
предоставляется
библиотекой
libcap, которая
доступна
по адресу:
http://www.kernel.org/pub/linux/libs/security/linux-privs
СМОТРИТЕ ТАКЖЕ¶
2010-09-20 | Linux |